
/*
http://xubenyang.me/416
NSLog还是是一件非常expensive的事情，主要体现在这两点：
1.NSLog在打印信息的同时要发送日志，效率低
2.程序一些调试信息通过NSLog发送到System Log之后，很容易被其他人查看到，对你程序的安全性造成了直接的威胁。除了通过xcode的oganizer可以查看console，在iPhone上有一个叫ConsoleLog的程序可以查看你的这些日志
 */


//调试时打开日志
#ifdef DEBUG    //DEBUG
//日志复杂度宏，值为：1-5
#define DLogInfoSimpleLeave 1


NSArray *allSubviews(UIView *aView);
NSArray *allApplicationViews();
NSArray *pathToView(UIView *aView);

//获取本地时间字符串
NSString *getDateString(NSDate *date);

//一个自定义的itoa。最好只处理正数
//负数时，只是简单的在最前边添加符号（这种情况对于二进制而言时不对的）
//算法：一直把取余得到的值组成字符串，最后翻转
//radix: 是基数的意思,即先将n转化为radix进制的数，范围介于2-36，比如10表示10进制。
//int，一般为32和64位。所以str定义为128位，绝对够了
char* myitoa(int n, char* str, int radix);

//打印日志需要的函数
void print0(id formatstring,...);
void print1(const char* function, int line, id formatstring,...);
void print2(const char* filename, const char* function, int line, id formatstring,...);
void print3(const char* filename, const char* function, int line, id formatstring,...);
void print4(const char* filename, const char* function, int line, id formatstring,...);

//dump打印
NSString* hexdump(NSData *data, NSString* prompt);


//0-4，使用printf实现；5，NSLog实现
//0,最简单
//1,函数(行数) 日志内容
//2,文件名 函数(行数) 日志内容
//3,时间 文件名 函数(行数) 日志内容
//4,日期 时间 文件名 函数(行数) 日志内容
//5,日期 时间 程序信息 文件名 函数(行数) 日志内容
#ifndef DLogInfoSimpleLeave
    #define DLogInfoSimpleLeave 1
#endif

#if (DLogInfoSimpleLeave == 0)
    #define DLog(fmt, ...) print0(fmt, ##__VA_ARGS__)
    //打印日志的另一种写法。该方法使用NSString的fomat方法直接格式化字符串
    //要注意的时fomat的写法
    //#define DLog(fmt, ...) printf("%s\n", [[NSString stringWithFormat:(@"" fmt), ##__VA_ARGS__] UTF8String]);
#elif (DLogInfoSimpleLeave == 1)
    #define DLog(fmt, ...) print1(__PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#elif (DLogInfoSimpleLeave == 2)
    #define DLog(fmt, ...) print2(__FILE__, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#elif (DLogInfoSimpleLeave == 3)
    #define DLog(fmt, ...) print3(__FILE__, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#elif (DLogInfoSimpleLeave == 4)
    #define DLog(fmt, ...) print4(__FILE__, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#else
    #define DLog(fmt, ...) do {\
    NSString* file = [[NSString alloc] initWithFormat:@"%s", __FILE__]; \
    NSLog((@"%@ %s(%d) " fmt), [file lastPathComponent], __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); \
    [file release]; \
    } while(0)
#endif

// 转变成字符串类型
#define	TO_STR(var)	#var
// 数字转换成bool类型字符串
#define	TO_BOOL_STR(intNum)	(((intNum) != 0) ? "YES" : "NO")

//fun(line) agrs...
#define DLogFun() DLog(@"")
#define DLogFunS() DLog(@"==>start")
#define DLogFunE() DLog(@"==>end")
#define DLogCount(str, p) DLog(@"%@,retainCount = %d", str, [p retainCount])
#define DLogCF CFShow 

//基础数据类型
#define DLogInt(intValue) DLog(@#intValue":%d", (intValue))
#define DLogIntHex(intValue) DLog(@#intValue":0x%x", intValue)
#define DLogIntOctal(intValue) DLog(@#intValue":O%o", intValue)
//负数的二进制有问题 
#define DLogIntBinary(intValue) do {\
char rst[129] = {0};\
myitoa(intValue, rst, 2);\
DLog(@"%s:%s",#intValue, rst);\
} while(0)

#define DLogLong(longValue) DLog(@#longValue":%ld", (longValue))
#define DLogChar(charValue) DLog(@#charValue":%c", (charValue))
#define DLogDouble(doubleValue) DLog(@#doubleValue":%f", (doubleValue))
#define DLogBOOL(b) DLog(@#b":%s", TO_BOOL_STR(b))
#define DLogPointer(p) DLog(@#p":%p", (p))

//常用数据类型
#define DLogStr(str) DLog(@#str":%@", str)
#define DLogCStr(cStr) DLog(@#cStr":%s", (cStr))
#define DLogSEL(sel) DLogCStr(sel)
#define DLogIMP(imp) DLogPointer(imp)
#define DLogRange(range) DLog(@#range"%@", NSStringFromRange(range))
#define DLogPoint(point) DLog(@#point"%@", NSStringFromCGPoint(point))
#define DLogSize(size) DLog(@#size"%@", NSStringFromCGSize(size))
#define DLogRect(rect) DLog(@#rect"%@", NSStringFromCGRect(rect))
#define DLogDate(date) DLog(@#date":%@", getDateString(date))
#define DLogTimeInterval(t) DLog(@#t":%.0f秒", t)
//#define DLogURL(url) DLog(@#url":%@", url)
#define DLogURL(url) DLog(@#url":%@", [url absoluteString])
#define DLogURLRequest(request) DLog(@#request":%@", [[request URL] absoluteString])
#define DLogException(e) DLog(@#e" %@:%@", [e name], [e reason])
#define DLogError(err) DLog(@#err":%@", err)


//view相关日志
//打印view树日志
#define DLogView(view) \
DLog(@"the view's subviews:"); \
CFShow(allSubviews(view))

#define DLogAllView() \
DLog(@"application window subviews:"); \
CFShow(allApplicationViews())	

#define DLogParentView(subview) \
DLog(@"path of the view:"); \
CFShow(pathToView(subview))

#define DLogViewFrame(view) DLogRect(view.frame)
#define DLogViewBounds(view) DLogRect(view.bounds)

#define DLogDataHex(data) DLog(@"%@", hexdump(data, @#data""))
#define DLogDataHex2(str, data) DLog(@"%@", hexdump(data, str))

#define DLogData(data, enc) do {\
NSString* aStr = [[NSString alloc] initWithData:data encoding:enc];\
DLog(@#data":%@", aStr);\
[aStr release];\
} while(0)

#define DLogDataUtf8(data) do {\
NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\
DLog(@#data":%@", aStr);\
[aStr release];\
} while(0)


#else   //DEBUG


#define DLog(...)
#define DLogFun()
#define DLogFunS()
#define DLogFunE()
#define DLogCount(p)
#define DLogCF

#define DLogInt(intValue)
#define DLogIntHex(intValue)
#define DLogIntOctal(intValue)
#define DLogIntBinary(intValue)
#define DLogLong(longValue)
#define DLogChar(charValue)
#define DLogDouble(doubleValue)
#define DLogBOOL(b)
#define DLogPointer(p)

#define DLogStr(str)
#define DLogCStr(cStr)
#define DLogSEL(sel)
#define DLogIMP(imp)
#define DLogRange(range)
#define DLogPoint(point)
#define DLogSize(size)
#define DLogRect(rect)
#define DLogDate(date)
#define DLogTimeInterval(t)
#define DLogURL(url)
#define DLogURLRequest(request)
#define DLogException(e)
#define DLogError(err)

#define DLogView(view)
#define DLogAllView()
#define DLogParentView(subview)
#define DLogViewFrame(view)
#define DLogViewBounds(view)

#define DLogDataHex(data)
#define DLogDataHex2(str, data)
#define DLogData(data, enc)
#define DLogDataUtf8(data)

#endif  //DEBUG






/*
 //真机日志文件
 //==========================================================
 - (void)redirectNSLogToDocumentFolder{
 // 把stderr重定向到该app的Document/curdata.log文件中
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *fileName =[NSString stringWithFormat:@"%@.log",[NSDate date]];
 NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
 freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
 }
 - (void)applicationDidFinishLaunching:(UIApplication *)application {
 // 真机测试时保存日志
 if ([CDeviceInfo getModelType] != SIMULATOR) {
 [self redirectNSLogToDocumentFolder];
 }
 }
 
 
 //模拟器日志文件
 //==========================================================
 - (void)redirectNSLogToDocumentFolder{
 //模拟器测试时，可以把stderr重定向到任何文件（已经测试），如~/wwp.log
 NSString *logFilePath = @"~/wwp.log";
 freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
 }
 
 - (void)applicationDidFinishLaunching:(UIApplication *)application {
 [self redirectNSLogToDocumentFolder];
 }
*/
